module repository.UserRepository;

import hunt.entity;
import hunt.logging;
import std.conv : to;
import std.array;
import bootstrap.DatabaseBootstrap;
import model.User;
import message.MsgDefine;
import core.stdc.time;
import std.uuid;
import hunt.framework;
class UserRepository: EntityRepository!( model.User.User , int)
{

  this()
  {
    super(defaultEntityManager());
  }

  //model.User.User findByOpenId(string openid)
	//{
	//	return find(new Condition("%s = '%s'" , Field.openid , openid));
	//}

  bool flushUser(message.MsgDefine.User user)
  {
    scope(exit)
    {
      _manager.close();
    }
    string code = randomUUID().toString();


    bool exist = false;
    auto u = findAllByUID(user.id);
    if(u !is null)
    {
        exist = true;
        auto update = _manager.createQuery!(model.User.User)("UPDATE User u SET u.updated = :updated, u.mobile = :mobile, u.nickname = :nickname, u.avatar = :avatar, u.username = :username , u.status = 1 WHERE u.id = :id");
        update.setParameter("updated",core.stdc.time.time(null));
        update.setParameter("mobile",user.mobile);
        update.setParameter("nickname",user.nickname);
        update.setParameter("avatar",user.avatar);
        update.setParameter("username",user.username);
        update.setParameter("id",user.id);
        try{
          update.exec();
        }
        catch(Exception e)
        {
          logError("update error : %s",e.msg);
          return false;
        }
        }else
    {
        auto us  = new model.User.User;
        us.id = to!uint(user.id);
        us.mobile = user.mobile;
        us.nickname = user.nickname;
        us.avatar = user.avatar;
        us.gender = to!uint(user.gender);
        us.birthday = user.birthday;
        us.created = core.stdc.time.time(null);
        us.status = 1;
        us.qrcode = code;
        us.updated = core.stdc.time.time(null);
        us.username = user.username;
        insert(us);
    }

    //auto insert = _manager.createQuery!(model.User.User)("INSERT INTO User u(u.id,u.mobile,u.nickname,u.avatar,u.gender,u.birthday,u.updated,u.status,u.QrCode) values (?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE updated = :updated, mobile = :mobile, nickname = :nickname, avatar = :avatar, status = 1, username = :username");
    //insert.setParameter(1,to!int(user.id));
    //insert.setParameter(2,user.mobile);
    //insert.setParameter(3,user.nickname);
    //insert.setParameter(4,user.avatar);
    //insert.setParameter(5,to!int(user.gender));
    //insert.setParameter(6,user.birthday);
    //insert.setParameter(7,core.stdc.time.time(null));
    //insert.setParameter(8,1);
    //insert.setParameter(9,code);
    //insert.setParameter("updated",core.stdc.time.time(null));
    //insert.setParameter("mobile",user.mobile);
    //insert.setParameter("nickname",user.nickname);
    //insert.setParameter("avatar",user.avatar);
    //insert.setParameter("username",user.username);

   // auto insert = _manager.createQuery!(model.User.User)("INSERT INTO logic_im_user (id,mobile,nickname,avatar,gender,birthday,updated,status,qrcode_id)" ~
   // " values (:id,:mobile,:nickname,:avatar,:gender,:birthday,:updated,:status,:qrcode_id) ON confilct(id) DO UPDATE SET updated = :updated, mobile = :mobile, nickname = :nickname, avatar = :avatar, status = 1, username = 'ss'");
   // insert.setParameter("id",to!int(user.id));
   // insert.setParameter("mobile",user.mobile);
   // insert.setParameter("nickname",user.nickname);
   // insert.setParameter("avatar",user.avatar);
   // insert.setParameter("gender",to!int(user.gender));
   // insert.setParameter("birthday",user.birthday);
   // insert.setParameter("updated",core.stdc.time.time(null));
   // insert.setParameter("status",1);
   // insert.setParameter("qrcode_id",code);
   //
   //
   // insert.setParameter("updated",core.stdc.time.time(null));
   // insert.setParameter("mobile",user.mobile);
   // insert.setParameter("nickname",user.nickname);
   // insert.setParameter("avatar",user.avatar);
   //// insert.setParameter("uname",user.username);
   //
   // insert.exec();
    return exist;
  }

  model.User.User[] findAllByUIDs(string[] uids)
	{
		if(uids.length == 0)
			return null;

    scope(exit)
    {
      _manager.close();
    }

    return _manager.createQuery!(model.User.User)("SELECT * FROM User a WHERE a.id IN (" ~ uids.join(",") ~ ");")
      .getResultList();
	}

  model.User.User findAllByUID(string uid)
  {
    infof("uid: %s", uid);
    try {
      if(uid.length > 10)
      {
        return null;
      }

      return find(new Condition("%s = %s" , Field.id , to!uint(uid)));
    }catch(Exception e)
    {
        warningf(e.msg);
        return null;
    }
  }
  
  model.User.User findByUserName(string username)
  {
		return find(new Condition("%s = '%s'" , Field.username , username));
  }

  model.User.User findAllByQr(string code)
  {
    if(code.length == 0)
      return null;

    return find(new Condition("%s = '%s'" , Field.qrcode , code));
  }

  model.User.User findByMobile(string mobile)
	{
		return find(new Condition("%s = '%s'" , Field.mobile , mobile));
	}


  model.User.User[] findByNickname(string nickname)
  {
    return findAll(new Condition("%s = '%s'" , Field.nickname , nickname));
  }

	int[] findAllByUIDs(int[] uids , long tick)
	{
    scope(exit)
    {
      _manager.close();
    }
		if(uids.length == 0)
			return null;

		int[] ids;
		auto strUids = to!string(uids);
		strUids = strUids[1 .. $ -1];
		auto users = findAll(new Condition("%s in (%s) and %s >= %s" , Field.id , strUids , Field.updated , tick));
		foreach(u ; users)
			ids ~= u.id;

		return ids;
	}

  string makeQrcode(int id)
  {
      string code = randomUUID().toString();
      scope(exit)
      {
        _manager.close();
      }
      auto update = _manager.createQuery!(model.User.User)(" update User u set u.QrCode = :QrCode where  " ~
      "u.id = :id" );
      update.setParameter("QrCode",code);
      update.setParameter("id",id);
      try{
        update.exec();
      }
      catch(Exception e)
      {
        logError("makeQrcode error : %s",e.msg);
      }
      return code;
  }

  int[] findAllOnline()
  {
    //scope(exit)
    //{
    //  _manager.close();
    //}
    //auto users =  _manager.createQuery!(model.User.User)("SELECT * FROM User a where a.status = 1;")
    //.getResultList();

    int[] rt;
    //foreach(model.User.User u ; users)
    //{
    //  rt ~= u.id;
    //}

    return rt;
  }

  void updateDeviceId(string token,int id, int src)
  {
    scope(exit)
    {
      _manager.close();
    }
    if (src == 100)
    {
      auto update = _manager.createQuery!(model.User.User)(" update User u set u.deviceIdIos = :deviceIdIos where  " ~
      "u.id = :id" );
      update.setParameter("deviceIdIos",token);
      update.setParameter("id",id);
      try{
        update.exec();
      }
      catch(Exception e)
      {
        logError("updateStatus error : %s",e.msg);
      }
    }else
    {
      auto update = _manager.createQuery!(model.User.User)(" update User u set u.deviceIdAnd = :deviceIdAnd where  " ~
      "u.id = :id" );
      update.setParameter("deviceIdAnd",token);
      update.setParameter("id",id);
      try{
        update.exec();
      }
      catch(Exception e)
      {
        logError("updateStatus error : %s",e.msg);
      }
    }

  }

  void resetStatus()
  {
    scope(exit)
    {
      _manager.close();
    }
    auto update = _manager.createQuery!(model.User.User)("update User u set u.status = :status");
    update.setParameter("status",0);
    try{
      update.exec();
    }
    catch(Exception e)
    {
      logError("resetStatus error : %s",e.msg);
    }
  }

  void updateStatus(int id , int online)
  {
    scope(exit)
    {
      _manager.close();
    }
      auto update = _manager.createQuery!(model.User.User)(" update User u set u.status = :status, u.updated = :now where  " ~
       "u.id = :id" );
      update.setParameter("status",online);
      update.setParameter("now",core.stdc.time.time(null));
      update.setParameter("id",id);
      try{
        update.exec();
      }
      catch(Exception e)
      {
        logError("updateStatus error : %s",e.msg);
      }
  }

  void setUnread(int id, uint ct)
  {
    scope(exit)
    {
      _manager.close();
    }
    auto update = _manager.createQuery!(model.User.User)("update User u set u.unread = :unread where u.id = :id" );
    update.setParameter("unread",ct);
    update.setParameter("id",id);
    try{
      update.exec();
    }
    catch(Exception e)
    {
      logError("setUnread error : %s",e.msg);
    }
  }


  void addUnread(int id)
  {
    scope(exit)
    {
      _manager.close();
    }
    auto update = _manager.createQuery!(model.User.User)("update User u set u.unread = unread + 1 where u.id = :id" );
    update.setParameter("id",id);
    try{
      update.exec();
    }
    catch(Exception e)
    {
      logError("addUnread error : %s",e.msg);
    }
  }

	//auto update = em.createQuery!(UserInfo)(" update UserInfo u set u.age = u.id, u.nickname = 'dd' where  " ~
  //"u.age > 2 and u.sex < :age2 and u.id = :id and u.nickname = :name " );
	//	// update UInfo u set u.age = 5 where u.id = 2
  //
	//update.setParameter("age",2);
	//update.setParameter("age2",55);
	//update.setParameter("id",1);
	//update.setParameter("name","tom");
	//try {
	//	warning(" update result : ",update.exec());
	//} catch(Exception ex) {
	//	warning("An exception");
	//}
  //
	//em.getTransaction().commit();


}
